#include "Surface.h"
#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#include "../common/lib/SDL_rotozoom.h"
#include <iostream>

Surface::Surface() {
	this->surface = SDL_CreateRGBSurface(SDL_SWSURFACE, 100, 30, GAME_COLOR_DEPTH, 0, 0, 0,	0);
}

Surface::Surface(int x, int y, int w, int h) {
	this->surface = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, GAME_COLOR_DEPTH, 0, 0, 0, 0);
	this->rectangle.x = x;
	this->rectangle.y = y;
	this->rectangle.w = w;
	this->rectangle.h = h;
}

Surface::Surface(int x, int y, SDL_Surface* surface) {
	this->surface = surface;
	this->rectangle.x = x;
	this->rectangle.y = y;
	if (surface != NULL) {
		this->rectangle.w = surface->clip_rect.w;
		this->rectangle.h = surface->clip_rect.h;
	}
}

Surface::Surface(int x, int y, int w, int h, SDL_Surface* surface) {
	this->rectangle.x = x;
	this->rectangle.y = y;
	this->rectangle.w = w;
	this->rectangle.h = h;
	if (surface == NULL) {
		this->surface = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, GAME_COLOR_DEPTH, 0, 0, 0,
				0);
		SDL_FillRect(this->surface, &this->rectangle,
				SDL_MapRGB(this->surface->format, 233, 233, 233));
	} else {
		this->surface = surface;
	}

}

const SDL_PixelFormat* Surface::getFormat(){
	return this->getSurface()->format;
}

Surface::Surface(int w, int h) {
	this->surface = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, GAME_COLOR_DEPTH, 0, 0, 0, 0);
	this->rectangle.x = 0;
	this->rectangle.y = 0;
	this->rectangle.w = w;
	this->rectangle.h = h;
}

Surface::Surface(int x, int y, std::string path) {
	this->loadSurfaceImage(path);
	this->rectangle.x = x;
	this->rectangle.y = y;
	if (surface != NULL) {
		this->rectangle.w = surface->clip_rect.w;
		this->rectangle.h = surface->clip_rect.h;
	}
}

Surface::Surface(SDL_Surface* SDLsurface) {
	this->surface = SDLsurface;
	this->rectangle.x = 0;
	this->rectangle.y = 0;
	if (this->surface != NULL) {
		this->rectangle.w = this->surface->w;
		this->rectangle.h = this->surface->h;
	}

}

Surface::~Surface() {
	if (this->surface != NULL) {
		SDL_FreeSurface(this->surface);
	}
}

SDL_Surface* Surface::getSurface() {
	return this->surface;
}

SDL_Rect Surface::getRectangle() {
	return this->rectangle;
}

Rectangle Surface::getRectangleStruc() {
	Rectangle rectangle;
	rectangle.x = this->rectangle.x;
	rectangle.y = this->rectangle.y;
	rectangle.w = this->rectangle.w;
	rectangle.h = this->rectangle.h;
	return rectangle;
}

void Surface::SetVideoMode(int width, int height, int bpp, Uint32 flags) {
	this->rectangle.w = width;
	this->rectangle.h = height;
	this->surface = SDL_SetVideoMode(width, height, bpp, flags);
}

void Surface::loadSurfaceImage(std::string path) {
	SDL_Surface* tempImage = NULL;
	SDL_Surface* finalImage = NULL;

	char* c_path = new char[path.size() + 1];strcpy
	(c_path, path.c_str());
	tempImage = IMG_Load(c_path);
	delete[] c_path;

	if (tempImage != NULL) {
		finalImage = SDL_DisplayFormatAlpha(tempImage);
		SDL_FreeSurface(tempImage);
		this->surface = finalImage;
		this->updateDimensions(&this->surface->clip_rect);
	} else {
		std::stringstream message;
		message << "NO se cargo la imagen de la superficie: " << path;
		Logger::log("Surface", "loadSurfaceImage", &message);
	}

}

void Surface::applySurface(Surface* surface) {
	SDL_Rect offset;
	offset.x = this->getRectangle().x;
	offset.y = this->getRectangle().y;

	if (SDL_BlitSurface(surface->getSurface(), NULL, this->surface, &offset)
			!= 0) {
		Logger::log("Surface", "applySurface", "No se pudo hacer blit");
	}
}

void Surface::applySurface(Surface* surface, Rectangle rectangle) {
	SDL_Rect offset;

	offset.x = rectangle.x;
	offset.y = rectangle.y;

	if (SDL_BlitSurface(surface->getSurface(), NULL, this->surface, &offset)
			!= 0) {
		Logger::log("Surface", "applySurface", "No se pudo hacer blit");
	}
}

Surface* Surface::clone() {
	Surface* clone = NULL;

	clone = new Surface(
			this->getRectangle().x,
			this->getRectangle().y,
			SDL_ConvertSurface(this->getSurface(), this->getSurface()->format,
					this->getSurface()->flags));

	return clone;
}

void Surface::resize(int w, int h) {
	SDL_Surface* srf = this->surface;
	if (this->surface->w != w || this->surface->h != h) {
		SDL_Surface* surface2 = new SDL_Surface();
		double zoomw = ((double) w) / ((double) this->rectangle.w);
		double zoomh = ((double) h) / ((double) this->rectangle.h);
		surface2 = zoomSurface(srf, zoomw, zoomh, SMOOTHING_OFF);

		SDL_FreeSurface(srf);
		this->surface = surface2;

		updateDimensions(&this->surface->clip_rect);
	}
}

void Surface::updateDimensions(SDL_Rect* rect) {
	this->rectangle.w = rect->w;
	this->rectangle.h = rect->h;
}
